package com.groupYLP.CouponNexus.merchant.admin.service.basics.chain;

import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 商家后管责任链上下文类，用于管理和执行商家后管责任链中的各个处理器
 * 实现了ApplicationContextAware接口，使用Spring框架能够自动注入应用上下文
 * 实现了CommandLineRunner接口，以便在应用启动后执行初始化逻辑
 */
@Component
public class MerchantAdminChainContext<T> implements ApplicationContextAware, CommandLineRunner {

    /**
     * 应用上下文，我们这里通过Spring IOC获取Bean实例
     */
    private ApplicationContext applicationContext;

    /**
     * 保存商家后管责任链实现类
     * <p>
     * Key：{@link MerchantAdminAbstractChainHandler#mark()}
     * Val：{@link MerchantAdminAbstractChainHandler} 一组责任链实现 Spring Bean 集合
     * <p>
     * 比如有一个优惠券模板创建责任链，实例如下：
     * Key：MERCHANT_ADMIN_CREATE_COUPON_TEMPLATE_KEY
     * Val：
     * - 验证优惠券信息基本参数是否必填 —— 执行器 {@link CouponTemplateCreateParamBaseVerifyChainFilter}
     * - 验证优惠券信息基本参数是否按照格式传递 —— 执行器 {@link CouponTemplateCreateParamBaseVerifyChainFilter}
     * - 验证优惠券信息基本参数是否正确，比如商品数据是否存在等 —— 执行器 {@link CouponTemplateCreateParamVerifyChainFilter}
     * - ......
     */
    private final Map<String, List<MerchantAdminAbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();

    /**
     * 责任链组件执行
     *
     * @param mark         责任链组件标识
     * @param requestParam 请求参数
     */
    public void handler(String mark, T requestParam) {
        //根据mark标识从责任链容器中获取一组责任链实现Bean集合
        List<MerchantAdminAbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
        if (CollectionUtils.isEmpty(abstractChainHandlers)) {
            throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
        }
        abstractChainHandlers.forEach(each -> each.handler(requestParam));
    }

    /**
     * 在springboot应用启动之后执行
     * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {
        //获取应用上下文中所有MerchantAdminAbstractChainHandler类型的Bean
        Map<String, MerchantAdminAbstractChainHandler> chainFilterMap = applicationContext.getBeansOfType(MerchantAdminAbstractChainHandler.class);
        chainFilterMap.forEach((beanName, bean) -> {
            //根据Bean的mark属性，从容器中获取对应的处理器列表，如果不存在则创建一个新的列表
            List<MerchantAdminAbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.getOrDefault(bean.mark(), new ArrayList<>());
            abstractChainHandlers.add(bean);
            abstractChainHandlerContainer.put(bean.mark(), abstractChainHandlers);
        });
        //对每个mark对应的处理器列表进行排序，以保证责任链的执行顺序
        abstractChainHandlerContainer.forEach((mark, unsortedChainHandlers) -> {
            unsortedChainHandlers.sort(Comparator.comparing(Ordered::getOrder));
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //Spring框架自动调用此方法，将应用上下文注入到本类中
        this.applicationContext = applicationContext;
    }
}